/*
 *  main.cpp
 *  Preview3D
 *
 *  Created by Alec Jacobson on 11/15/10.
 *  Copyright 2010 New York University. All rights reserved.
 *
 */

#include "Preview3D.h"

#include <cstdlib>
#include <cstdio>
#include <cmath>

#ifdef __APPLE__
#   include <GLUT/glut.h>
#else
#   include <GL/glut.h>
#endif

Preview3D * preview_3D;

// Callback function called by GLUT to render screen
void Display(void)
{
  preview_3D->draw(glutGet(GLUT_ELAPSED_TIME));
  // Present frame buffer
  glutSwapBuffers();
  // Recall Display at next frame
  glutPostRedisplay();
}


// Callback function called by GLUT when window size changes
void Reshape(int width, int height)
{
  preview_3D->resize(width,height);
}

// Function called at exit
void Terminate(void)
{ 
  delete preview_3D;
}

void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
{
  if(glutState==1){
    preview_3D->mouse_up(mouse_x,mouse_y);
  }else if(glutState==0){
    preview_3D->mouse_down(mouse_x,mouse_y);
  }
}
void mouse_move(int mouse_x, int mouse_y)
{
  if(!preview_3D->mouse_move(mouse_x,mouse_y))
  {
  }
}

// Main
int main(int argc, char *argv[])
{

  // Initialize GLUT
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  glutInitWindowSize(800, 600);
  // Center window
  glutInitWindowPosition(
      glutGet(GLUT_SCREEN_WIDTH)/2-glutGet(GLUT_INIT_WINDOW_WIDTH)/2,
      glutGet(GLUT_SCREEN_HEIGHT)/2-glutGet(GLUT_INIT_WINDOW_HEIGHT)/2);
  glutCreateWindow("Preview3D");
  glutCreateMenu(NULL);
  // Set GLUT callbacks
  glutDisplayFunc(Display);
  glutReshapeFunc(Reshape);
  atexit(Terminate);  // Called after glutMainLoop ends
  
  preview_3D = new Preview3D(glutGet(GLUT_ELAPSED_TIME));
  // Hook up AntTweakBar to GLUT events
  // - Directly redirect GLUT mouse button events to AntTweakBar
  glutMouseFunc((GLUTmousebuttonfun)mouse);
  // - Directly redirect GLUT mouse motion events to AntTweakBar
  glutMotionFunc(mouse_move);
  // - Directly redirect GLUT mouse "passive" motion events to AntTweakBar (same as MouseMotion)
  glutPassiveMotionFunc(mouse_move);
  // - Directly redirect GLUT key events to AntTweakBar
  glutKeyboardFunc((GLUTkeyboardfun)TwEventKeyboardGLUT);
  // - Directly redirect GLUT special key events to AntTweakBar
  glutSpecialFunc((GLUTspecialfun)TwEventSpecialGLUT);
  // - Send 'glutGetModifers' function pointer to AntTweakBar;
  //   required because the GLUT key event functions do not report key modifiers states.
  TwGLUTModifiersFunc(glutGetModifiers);
  // Load the given mesh
  char * obj_file_name;
  if(argc < 0 || 
    argv[1] == NULL || 
    !preview_3D->load_mesh_from_file(argv[1]))
  {
    //preview_3D->load_mesh_from_file("/Users/ajx/Documents/Preview3D/data/cow.obj");
    preview_3D->load_mesh_from_file("/Users/ajx/Downloads/models/fandisk.off");
  }

  // Call the GLUT main loop
  glutMainLoop();
  return 0;
}

